package com.kantboot.wechat.applet.entity;


import com.alibaba.fastjson.JSON;
import com.kantboot.wechat.applet.config.WechatAppletConfig;
import com.kantboot.wechat.applet.entity.ex.AppletUserInfoEntityException;
import com.kantboot.wechat.applet.util.AesCbcUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.SneakyThrows;
import lombok.experimental.Accessors;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Component
public class AppletUserInfoEntity {

    @Resource
    WechatAppletConfig wechatAppletConfig;

    @Data
    @Accessors(chain = true)
    @NoArgsConstructor
    @AllArgsConstructor
    public static class Param {
        private String code;
        private String encryptedData;
        private String iv;
    }

    @Data
    @Accessors(chain = true)
    @NoArgsConstructor
    @AllArgsConstructor
    public static class UserInfoResult {
        private String openId;
        private String nickname;
        private Integer gender;
        private String city;
        private String province;
        private String country;
        private String avatarUrl;
        private String unionid;
        private Integer errcode;
        private Integer errmsg;
    }

    @Data
    @Accessors(chain = true)
    @NoArgsConstructor
    @AllArgsConstructor
    public static class PhoneNumberResult {
        private String phoneNumber;
        private String purePhoneNumber;
        private String countryCode;
        private String openId;
        private String unionid;
    }

    public static <T> T decrypt(WechatAppletConfig wechatAppletConfig,Param param,Class<T> clazz){

        if(param.getCode()==null) {
            throw new AppletUserInfoEntityException.NoCodeException("没有Code参数");
        }
        if(param.getEncryptedData()==null){
            throw new AppletUserInfoEntityException.NoEncryptedDataException("没有EncryptedData参数");
        }
        if(param.getIv()==null){
            throw new AppletUserInfoEntityException.NoIvException("没有iv参数");
        }

        AuthCode2SessionEntity.Result aC2SEResult
                =new AuthCode2SessionEntity
                    .Result()
                    .setWechatAppletConfig(wechatAppletConfig)
                    .analysis(new AuthCode2SessionEntity.Param().setJs_code(param.getCode()));
        try {
            String decrypt= AesCbcUtil.decrypt(
                    param.getEncryptedData(),
                    aC2SEResult.getSessionKey(),
                    param.getIv()
            );
            return JSON.parseObject(decrypt,clazz);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public UserInfoResult decryptUserInfoResult(Param param){

        if(param.getCode()==null) {
            throw new AppletUserInfoEntityException.NoCodeException("没有Code参数");
        }
        if(param.getEncryptedData()==null){
            throw new AppletUserInfoEntityException.NoEncryptedDataException("没有EncryptedData参数");
        }
        if(param.getIv()==null){
            throw new AppletUserInfoEntityException.NoIvException("没有iv参数");
        }

        AuthCode2SessionEntity.Result aC2SEResult
                =new AuthCode2SessionEntity
                .Result()
                .setWechatAppletConfig(wechatAppletConfig)
                .analysis(new AuthCode2SessionEntity.Param().setJs_code(param.getCode()));
        try {
            String decrypt= AesCbcUtil.decrypt(
                    param.getEncryptedData(),
                    aC2SEResult.getSessionKey(),
                    param.getIv()
            );

            return JSON.parseObject(decrypt,UserInfoResult.class);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @SneakyThrows
    public PhoneNumberResult decryptPhoneNumberResult(Param param){

        if(param.getCode()==null) {
            throw new AppletUserInfoEntityException.NoCodeException("没有Code参数");
        }
        if(param.getEncryptedData()==null){
            throw new AppletUserInfoEntityException.NoEncryptedDataException("没有EncryptedData参数");
        }
        if(param.getIv()==null){
            throw new AppletUserInfoEntityException.NoIvException("没有iv参数");
        }

        AuthCode2SessionEntity.Result aC2SEResult
                =new AuthCode2SessionEntity
                .Result()
                .setWechatAppletConfig(wechatAppletConfig)
                .analysis(new AuthCode2SessionEntity.Param().setJs_code(param.getCode()));

        try {
            String decrypt= AesCbcUtil.decrypt(
                    param.getEncryptedData(),
                    aC2SEResult.getSessionKey(),
                    param.getIv()
            );
            PhoneNumberResult phoneNumberResult=JSON.parseObject(decrypt,PhoneNumberResult.class)
                    .setOpenId(aC2SEResult.getOpenid())
                    .setUnionid(aC2SEResult.getUnionId());

            return JSON.parseObject(decrypt,PhoneNumberResult.class);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}
